package org.gl.customview;

import org.gl.utils.lg;

import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Paint.Style;
import android.graphics.Point;
import android.graphics.Rect;
import android.util.AttributeSet;
import android.util.DisplayMetrics;
import android.view.GestureDetector;
import android.view.GestureDetector.OnGestureListener;
import android.view.MotionEvent;
import android.view.View;
import android.view.animation.AnimationUtils;
import android.widget.LinearLayout;
import android.widget.Scroller;

public class MultiTouchLinearLayout extends LinearLayout implements
		OnGestureListener {
	/**
	 * the first down point x coordinate
	 */
	private float x1;
	/**
	 * the first down point y coordinate
	 */
	private float y1;
	private float x_current;
	private float y_current;
	/**
	 *  the secend down point x coordinate
	 */
	private float x2;
	private float y2;
	private float x2_current;
	private float y2_current;
	private Paint paint;
	private GestureDetector mGestureDetector;
	View.OnClickListener MainActivity;
	final int tag = lg.z_logDegree_View_mainActivity_OnGestureListener;
	private int width = -1;
	private int height = -1;
	private Point centerPoint;
	private int animCount = 0;
	private int animMaxCount = 5;
	private int state;
	private final int SCENCE_MOVING = 1;
	private final int SCENCE_MOVING_PRE = 3;
	private final int SCENCE_SCALE_PRE = 4;
	private final int SCENCE_SCALEING = 2;
	private final int SCENCE_STOP = 0;
	private Scroller mScroller;
	DisplayMetrics metrics;
	float r = 30;
	private float oldDistance;
	private long lastTouchDownTime;
	private boolean isScroll;
	private int scroll_duration_time = 1000;
	private int scroll_speed = 200;
	private int scale_speed = 200;
	private MultiTouchEventListener mMultiTouchEventListener;
	private boolean isTouchAble = true;
	private float newDistance;
	/**
	 * the viewGroup vertex coordinate
	 */
	Rect rect;
	/**
	 * 鏄惁澶勪簬缂╂斁鍔ㄧ敾涓�
	 */
	private boolean isScale;

	public void setMultiTouchEventListener(
			MultiTouchEventListener mMultiTouchEventListener) {
		this.mMultiTouchEventListener = mMultiTouchEventListener;
	}

	public MultiTouchLinearLayout(Context context, AttributeSet attrs) {
		super(context, attrs);
		paint = new Paint();
		paint.setAntiAlias(true);
		mGestureDetector = new GestureDetector(context, this);
		mScroller = new Scroller(context, AnimationUtils.loadInterpolator(
				context, android.R.interpolator.bounce));
		metrics = getResources().getDisplayMetrics();
	}
	@Override
	protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
		width = getWidth();
		height = getHeight();
		if (width > 0 && height > 0) {
			centerPoint = new Point(width / 2, height / 2);
		} else {
			centerPoint = new Point(1, 1);
		}
		r = (r < width / 20) ? width / 20 : r;
		rect = new Rect(getLeft(), getTop(), getRight(), getBottom());
		super.onMeasure(widthMeasureSpec, heightMeasureSpec);
	}

	@Override
	public boolean onTouchEvent(MotionEvent event) {
		postInvalidate();
		if (isTouchAble == false) {
			return true;
		}
		try {
			x_current = event.getX();
			y_current = event.getY();

			switch (event.getAction() & MotionEvent.ACTION_MASK) {
			case MotionEvent.ACTION_DOWN:
				x1 = event.getX();
				y1 = event.getY();
				state = SCENCE_MOVING_PRE;
				lg.info(tag, "SCENCE_MOVING_PRE");
				lastTouchDownTime = System.currentTimeMillis();
				mGestureDetector.onTouchEvent(event);
				break;
			case MotionEvent.ACTION_POINTER_DOWN:
				state = SCENCE_SCALE_PRE;
				oldDistance = 0;
				newDistance = 0;
				x2 = event.getX(1);
				y2 = event.getY(1);
				lg.info(tag, "SCENCE_SCALE_PRE x2 y2 (" + x2 + "," + y2);
				oldDistance = (float) Math.sqrt((x1 - x2) * (x1 - x2)
						+ (y1 - y2) * (y1 - y2));
				invalidate();
				break;
			case MotionEvent.ACTION_MOVE:
				if (state == SCENCE_SCALE_PRE || state == SCENCE_SCALEING) {// 缂╂斁妯″紡
					if (oldDistance > 10f) {
						x_current = event.getX(0);
						y_current = event.getY(0);
						x2_current = event.getX(1);
						y2_current = event.getY(1);
						newDistance = (float) Math
								.sqrt((x_current - x2_current)
										* (x_current - x2_current)
										+ (y_current - y2_current)
										* (y_current - y2_current));
						state = SCENCE_SCALEING;
						lg.info(tag, "ACTION_MOVE_SCENCE_SCALEING");
						invalidate();
					}
				} else if (state == SCENCE_MOVING_PRE || state == SCENCE_MOVING) {// 鎷栨嫿妯″紡
					lg.info(tag, "try make SCENCE_MOVING_");
					if (Math.abs(event.getX() - x1) > 10
							&& Math.abs(event.getY() - y1) >= 10) {
					 state = SCENCE_MOVING;
					 lg.info(tag, "SCENCE_MOVING");
//					 invalidate();
					 return mGestureDetector.onTouchEvent(event);//FIXME
//					 鍗曠偣鎷栧姩闀滃ご鐨勫疄鐜� return false;
					 }
				}
//				lg.info(tag, "onTouchEvent");
				break;
			// 鏈夋墜鎸囨姮璧凤紝灏嗘ā寮忚涓篘ONE
			case MotionEvent.ACTION_UP:
				lg.info(tag, "ACTION_UP");
				if (state == SCENCE_MOVING) {
					scroll_duration_time = (int) (Math
							.sqrt((event.getX() - centerPoint.x)
									* (event.getX() - centerPoint.x)
									+ (event.getY() - centerPoint.y)
									* (event.getY() - centerPoint.y)))
							/ scroll_speed;
					startScrollAnim(event, scroll_duration_time * 1000);
					lg.info(tag, "up SCENCE_MOVING");
				} else if (state == SCENCE_SCALEING) {
					startScaleAnim(event,
							(int) Math.abs(newDistance - oldDistance)
									/ scale_speed * 1000);
					lg.info(tag, " up SCENCE_SCALEING");
				} else {
					if (System.currentTimeMillis() - lastTouchDownTime < 300
							&& Math.abs(event.getX() - x1) <= 10
							&& Math.abs(event.getY() - y1) <= 10) {
						lg.info(tag, "onClick");
						if (MainActivity != null) {
							MainActivity.onClick(null);
						}
					}
				}
				break;
			case MotionEvent.ACTION_OUTSIDE:
				state = SCENCE_STOP;
				break;
			default:
			}
			return true;
		} catch (Exception e) {
			e.printStackTrace();
			return true;
		}

	}
	protected void startScaleAnim(MotionEvent event, int duration) {
		isScale = true;
		mScroller.startScroll(0, 0, (int) (newDistance - oldDistance), 0,
				duration);
		if (mMultiTouchEventListener != null) {
			mMultiTouchEventListener.scale(rect, newDistance, oldDistance, x1,
					y1, x_current, y_current, x2_current, y2_current,
					scale_speed);
		}
		isTouchAble = false;
		invalidate();
	}

	protected void startScrollAnim(MotionEvent event, int duration) {
		isScroll = true;
		lg.info(tag, "startScroll" + duration);
		mScroller.startScroll((int) event.getX(), (int) event.getY(),
				(int) (centerPoint.x - event.getX()),
				(int) (centerPoint.y - event.getY()), duration);
		isTouchAble = false;
		invalidate();
		if (mMultiTouchEventListener != null) {
			mMultiTouchEventListener.scroll(rect, event.getX(), event.getY(),
					centerPoint.x, centerPoint.y, scroll_speed, scroll_speed);
		}

	}
	/**
	 * if a ViewGroup background is null ,the funtion "ondraw" will not be call.
	 */
	@Override
	protected void onDraw(Canvas canvas) {
		super.onDraw(canvas);
		lg.info(tag, "onDraw");
		if (animCount >= animMaxCount) {
			animCount = 0;
		} else {
			animCount++;
		}
		
		if (state == SCENCE_MOVING) {
			paint.setColor(Color.RED);
			paint.setStyle(Style.FILL);//
			paint.setStrokeWidth(5);//
			canvas.drawCircle(x_current, y_current, r, paint);
			canvas.drawLine(x_current, y_current, centerPoint.x, centerPoint.y,
					paint);
			canvas.drawText("moving...", centerPoint.x, centerPoint.y / 3,
					paint);
			paint.setStyle(Style.STROKE);
			for (int i = 0; i < animMaxCount; i++) {
				paint.setStrokeWidth(animMaxCount - animCount);
				paint.setColor(Color.GREEN);
				canvas.drawCircle(centerPoint.x, centerPoint.y, r - animCount,
						paint);
			}
			if (mScroller.computeScrollOffset() && isScroll) {
				x_current = mScroller.getCurrX();
				y_current = mScroller.getCurrY();
				lg.info(tag, "cn scroll Animing 璧风偣鍧愭爣===(" + x1 + "," + y1
						+ ")");
				lg.info(tag, "cn scroll Animing 褰撳墠鍧愭爣===(" + x_current
						+ "," + y_current + ")");
				invalidate();
				return;
			} else if (mScroller.isFinished() && isScroll) {
				// if (Math.abs(mScroller.getCurrX() - centerPoint.x) <= 10
				// && Math.abs(mScroller.getCurrY() - centerPoint.y) <= 10) {
				lg.info(tag, " scroll Animing  stop");
				lg.info(tag,
						"cn scroll Animing 褰撳墠鍧愭爣===(" + mScroller.getCurrX()
								+ "," + mScroller.getCurrY() + ")");
				x_current = centerPoint.x;
				y_current = centerPoint.y;
				state = SCENCE_STOP;
				isScroll = false;
				isTouchAble = true;
				invalidate();
				mMultiTouchEventListener.scrollStop();
				// }
			}
		} else if (state == SCENCE_SCALEING || state == SCENCE_SCALE_PRE) {

			paint.setStyle(Style.STROKE);
			paint.setStrokeWidth(5);

			paint.setColor(0xc0c0c0c0);
			canvas.drawCircle((x1 + x2) / 2, (y1 + y2) / 2, oldDistance / 2,
					paint);
			paint.setColor(0xc0888888);
			// canvas.drawLine((x1 + x2)/2, (y1+y2)/2, x_current, y_current,
			// paint);
			// canvas.drawLine((x1 + x2)/2, (y1+y2)/2, x2_current, y2_current,
			// paint);

			if (mScroller.computeScrollOffset() && isScale) {
				newDistance = oldDistance + mScroller.getCurrX();
				lg.info(tag, "cn scale  Animing " + mScroller.getCurrX()
						+ "缂╂斁璺濈 newDistance===(" + newDistance + ")");
				invalidate();
				canvas.drawCircle((x1 + x2) / 2, (y1 + y2) / 2,
						newDistance / 2, paint);
				return;
			} else if (mScroller.isFinished() && isScale) {
				newDistance = oldDistance;
				// if (Math.abs(mScroller.getCurrX() - centerPoint.x) <= 10
				// && Math.abs(mScroller.getCurrY() - centerPoint.y) <= 10) {
				lg.info(tag, " scale Animing  stop");
				lg.info(tag,
						"cn scale Animing 褰撳墠鍧愭爣===(" + mScroller.getCurrX()
								+ "," + mScroller.getCurrY() + ")");
				x_current = centerPoint.x;
				y_current = centerPoint.y;
				state = SCENCE_STOP;
				isScale = false;
				isTouchAble = true;
				for (int i = 0; i < animMaxCount; i++) {
					paint.setStrokeWidth(animMaxCount - animCount);
					paint.setColor(Color.GREEN);
					canvas.drawCircle((x1 + x2) / 2, (y1 + y2) / 2,
							newDistance / 2, paint);
				}
				invalidate();
				mMultiTouchEventListener.ScaleStop();
				// }
			} else {
				canvas.drawCircle((x1 + x2) / 2, (y1 + y2) / 2,
						newDistance / 2, paint);
			}

		} else if (state == SCENCE_STOP) {
			paint.setColor(Color.TRANSPARENT);
			canvas.drawRect(0, 0, width, height, paint);
		}

	}

	public void setOnClickEventImp(View.OnClickListener view) {
		MainActivity = view;
	}

	@Override
	public boolean onDown(MotionEvent e) {
		lg.info(tag, "onDown");
		return false;
	}

	@Override
	public void onShowPress(MotionEvent e) {
		lg.info(tag, "onShowPress");

	}

	@Override
	public boolean onSingleTapUp(MotionEvent e) {
		lg.info(tag, "onClick");
		if (MainActivity != null) {
			MainActivity.onClick(null);
		}
		return false;
	}

	@Override
	public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX,
			float distanceY) {
		lg.info(tag, "onScroll");
		state = SCENCE_MOVING;
		invalidate();
		return true;
	}

	@Override
	public void onLongPress(MotionEvent e) {
		lg.info(tag, "onLongPress");
	}

	@Override
	public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX,
			float velocityY) {
		lg.info(tag, "onFling");
		return false;
	}

}
